import p2
import pickle
import math
import copy
import os
import random
from concurrent.futures import ProcessPoolExecutor
import multiprocessing as mp
import asyncio,time
from email.mime.text import MIMEText
from smtplib import SMTP_SSL
from email.header import Header
from email.message import EmailMessage
from tqdm import tqdm
readpath = r'G:\software\work\finalhomework\video_detection\video'

with open(r'G:\software\work\finalhomework\video_detection\label.pkl', 'rb') as f:
    label=pickle.load(f)

time1 = time.time()

class NoneReturnError(Exception):
    '''
    Raised when 每次检测都异常且检测异常数大于10
    '''
    def __init__(self,message):
        self.message=message
        self.send()
    def send(self):
        send(self.message)

class ZeroOutputError(Exception):
    def __init__(self,error_file,file):
        self.error_file=error_file
        self.file=file
        self.handle(self.error_file)
    def handle(self,error_file):
        print('error_file:',error_file)
        for loc in error_file:
            detect_result=self.file
            detect_result.pop(loc)
            label.pop(loc)

def ZeroOutput(error_file):
    for root, dirs, files in os.walk(readpath): 
        for i, file in enumerate(files,start=1):
            if i in error_file:
                m=file.split('.')
                if m[1]!='avi':
                    return 'File error'
    for root, dirs, files in os.walk(readpath): 
        for i, file in enumerate(files,start=0):
            if i in error_file:
                print(file)

def main_map():
    '''
    用多进程处理检测任务
    '''
    detect_result = []
    pool=mp.Pool(os.cpu_count()-1)
    flag=0
    for root, dirs, files in os.walk(readpath):  #仅循环了一次
        for i, file in enumerate(files,start=1):
            if i==12:
                print(file)
                try:
                    detect_result.append(pool.apply_async(p2.detect,(root,file, i)))
                    #f = p2.detect(root, file, i)
                except Exception :  #某一部预告片检测异常
                    flag+=1
                    send('Something error when detecting {}! '.format(file))
                    continue
            else:
                break
            if flag>10 and flag==i:  #一堆预告片检测异常,说明代码有问题，引发异常以免发送过多邮件导致邮件地址被封
                raise NoneReturnError('Detection error!')
            #print(f)
            #detect_result.append(f)
        #detect_result=[executor.submit(p2.detect,(file,root,i)).result() for i,file in enumerate(files) for root,dirs,files in os.walk(readpath)]
    pool.close()
    pool.join()
    for res in detect_result:
        res=res.get()
    return detect_result  # 列表，包含储存每个预告片图像识别信息的字典


def preprocess1(detect_result,del_person=False):
    '''
    数据预处理
    先归一化,将检测结果全部变成百分比,再提取出数字
    返回结果：
    detect_result_number: 2维列表，每个列表包含一个预告片的结果(仅包含数字结果)
    detect_result: 列表，每个元素都是包含储存每个预告片图像识别信息的字典
    train_data
    test_data
    train_label
    test_label
    '''
    if del_person==True:
        for result in detect_result:
            result.pop('person')
    detect_result_number=[]
    #bar1=tqdm(detect_result)
    flag=0
    error_file=[]
    for i,result in enumerate(detect_result,start=0):
        #bar1.set_description('Now get {}th item'.format(i+1))
        sum = 0
        for item in result:
            sum += result[item]
        try:
            for item in result:
                result[item] = (result[item])/sum  # 改成每个元素所占百分比
        except ZeroDivisionError:
            print('-----------------',i)
            flag=+1
            print('File error')
            error_file.append(i)
            continue
    #ZeroOutput(error_file)  

    if flag>0:
        try:
            raise ZeroOutputError(error_file,detect_result)
        except ZeroOutputError:
            print('Handling file error')
    
    for i,result in enumerate(detect_result,start=0):
        detect_result_number.append([])
        for item in result:
            detect_result_number[i].append(result[item])  
        
    a = math.ceil(0.7*(len(detect_result)))
    #print('a:',a)
    train_label=[]
    test_label=[]
    selection=random.sample(range(0,len(detect_result)),a)  

    for i,grade in enumerate(label):   #对label分割测试集和训练集
        if i in selection:
            train_label.append(grade)
        else:
            test_label.append(grade)
    print(len(test_label),len(train_label))
    
    bar2=tqdm(detect_result_number)  #仅对detect_result_number分割测试集和训练集,detect_result用于可视化分析，描述性统计

    train_data = []
    test_data = []

    for i, result in enumerate(bar2,start=0):
        bar2.set_description('Now get {}th item'.format(i+1))
        if i in selection:
            train_data.append(result) 
        else:
            test_data.append(result)
    print('Process complete.')
    return detect_result, detect_result_number, train_data, test_data, train_label, test_label

def send(*argv):
    '''
    检测结束或出bug之后发邮件通知
    '''
    smtp_server = 'smtp.qq.com'
    from_addr = '908168202@qq.com'
    to_addr = '13368939416@163.com'
    smtp_password = 'nwrfqeprauvmbddb'
    port = 465

    global time1
    if argv == ():
        msg = MIMEText('Detection sucessfully complete!\n:)\nUsing {} minutes!'.format(
            (time.time()-time1)/60.0), 'plain', 'utf-8')
    else:
        msg = MIMEText(*argv, 'plain', 'utf-8')
    msg['From'] = Header(from_addr, 'utf-8')
    msg['To'] = Header(to_addr, 'utf-8')
    msg['subject'] = Header('SMTP-test', 'utf-8')

    server = SMTP_SSL(smtp_server, port)
    server.set_debuglevel(1)
    server.login(from_addr, smtp_password)
    print('login in success')
    server.sendmail(from_addr, [to_addr], msg.as_string())
    server.quit()
    print('suscess')

async def picklefile(i1,i2):
    with open(r'G:\software\work\finalhomework\video_detection\record_{}.pkl'.format(i2), 'wb') as f:
        pickle.dump(i1, f)
    print(f'File of {i2} sccesfully serialized.')
    
async def writefile(i1,i2):
    await picklefile(i1,i2)

if __name__ == '__main__':
    '''
    detect_result1 = main_map()
    if detect_result1!='error':
    with open(r'G:\software\work\finalhomework\video_detection\detect_result1.pkl', 'wb') as f:
        pickle.dump(detect_result1,f)
    send()
    
    '''
    with open(r'G:\software\work\finalhomework\video_detection\detect_result1.pkl', 'rb') as f:
            detect_result1=pickle.load(f)
    #print(detect_result1)
    print('****************')
    detect_result, detect_result_number, train_data, test_data, train_label, test_label = preprocess1(
        detect_result1, del_person=False)
    print('-----------------')
    print(len(train_data),len(test_data),len(train_label),len(test_label))
    l1 = [detect_result, detect_result_number , train_data, test_data, train_label, test_label]
    l2 = ['detect_result', 'detect_result_number', 'train_data', 
          'test_data', 'train_label', 'test_label']
    time1=time.time()
    loop=asyncio.get_event_loop()
    tasks=[writefile(i1,i2) for i1, i2 in zip(l1, l2)]
    loop.run_until_complete(asyncio.wait(tasks))
    loop.close()
    print('Using {} seconds.'.format(time.time()-time1))

    '''time2=time.time()
    for i1, i2 in zip(l1, l2):
        with open(r'G:\software\work\finalhomework\video_detection\record_{}.pkl'.format(i2), 'wb') as f:
            pickle.dump(i1, f)
    print(time.time()-time2)'''  #文件太小，好像还不如不用协程，直接循环序列化文件
    
    
    
    

